import { BlockNoteView } from "@blocknote/shadcn";
import {
  createReactBlockSpec,
  createReactInlineContentSpec,
  SuggestionMenuController,
  useCreateBlockNote,
  getDefaultReactSlashMenuItems,
  type DefaultReactSuggestionItem
} from "@blocknote/react";
import "@blocknote/shadcn/style.css";
import { zh } from "@blocknote/core/locales";
import {
  BlockNoteSchema,
  defaultBlockSpecs,
  defaultInlineContentSpecs,
  defaultStyleSpecs,
  filterSuggestionItems,
  insertOrUpdateBlock
} from "@blocknote/core";
import { CustomSocketProvider } from "./CustomSocketProvider";
import * as Y from "yjs";
import { cursorRender } from "../cursorRender";
import { useParams } from "react-router-dom";
import { useEffect, useMemo, useState, useCallback } from "react";
import { useOfflineDocSync } from "../../hooks/useOfflineDocSync";
// 注意：原始的重组件已被懒加载包装器替代
// import { MindMapBlockView } from "@/components/MindmapBlockView";
// import { FlowchartBlockView } from "@/components/FlowchartBlockView";
// import { WhiteboardBlockView } from "@/components/WhiteboardBlockView";
// import { LazyBlockContainer } from "../../components/LazyBlockContainer"; // 预留给将来的块级懒加载
import { LazyMindMapWrapper, LazyFlowchartWrapper, LazyWhiteboardWrapper } from "../../components/LazyHeavyComponents";
import { EditorErrorBoundary } from "../../components/EditorErrorBoundary";

// 按文档实例化独立的 Y.Doc（避免不同文档共用同一个 Y.Doc 导致内容错乱/空白）

// 文档 需求 不要去支持导出 为了防止泄密！！

// 思维导图，流程图，画板支持 导出为图片！！！

const schema = BlockNoteSchema.create({
  blockSpecs: {
    ...defaultBlockSpecs,
    blockAI: createReactBlockSpec(
      {
        type: "blockAI",
        content: "none",
        propSchema: {
          id: {
            default: "ai-block"
          },
          title: {
            default: "AI Block"
          },
          description: {
            default: "这是一个AI块的描述."
          },
          content: {
            default: "AI生成的内容"
          }
        }
      },
      {
        render: props => {
          const { title, description, content } = props.block.props;
          return (
            <div className="p-4 border rounded-lg shadow-md bg-gray-50 w-lg">
              <h3 className="text-lg font-semibold text-blue-600">{title}</h3>
              <p className="text-xs text-gray-500">{description}</p>
              <div className="mt-2 p-2 bg-white border rounded text-lg text-black">
                <span>内容:</span>
                {content}
              </div>
            </div>
          );
        }
      }
    ),
    blockSignature: createReactBlockSpec(
      {
        type: "blockSignature",
        content: "none",
        propSchema: {
          id: {
            default: "signature-block"
          },
          name: {
            default: "签名"
          }
        }
      },
      {
        render: props => {
          const { name } = props.block.props;
          return (
            <div className="flex item-center justify-between p-2 border rounded shadow-md bg-gray-100">
              <span className="text-sm font-semibold text-gray-600">{name}</span>
            </div>
          );
        }
      }
    ),
    mindMap: createReactBlockSpec(
      {
        type: "mindMap",
        content: "none", // 画布由 React 控制
        propSchema: {
          //BlockNote 每个块自带 block.id（内部唯一），用于我们拼接 mindmap:<blockId>///mindmap-json:<blockId> 即可。
          data: { default: "" }, // 用空字符串作为默认，PropSpec 推断为 string
          width: { default: 900 }, // 数字默认值，PropSpec 推断为 number
          height: { default: 600 } // 数字默认值，PropSpec 推断为 number
        }
      },
      {
        render: props => <LazyMindMapWrapper block={props.block} editor={props.editor} />
      }
    ),
    flowchart: createReactBlockSpec(
      {
        type: "flowchart",
        content: "none",
        propSchema: { width: { default: 900 }, height: { default: 600 } }
      },
      {
        render: props => <LazyFlowchartWrapper block={props.block} editor={props.editor} />
      }
    ),
    whiteboard: createReactBlockSpec(
      {
        // tldraw 白板块（方案一：JSON 快照）
        type: "whiteboard",
        content: "none",
        propSchema: {
          // data.tldrawJson 保存 tldraw 快照；version 用于并发覆盖校验/历史
          // 注意：默认 tldrawJson 应为 null，而不是 {}，避免 loadSnapshot 迁移期读取 schemaVersion 报错
          data: { default: { version: 1, tldrawJson: null, preview: null, assets: [] } } as any,
          width: { default: 900 },
          height: { default: 600 }
        }
      },
      {
        // 交由 LazyWhiteboardWrapper 渲染（懒加载 + 内部负责快照读写与节流）
        render: props => <LazyWhiteboardWrapper block={props.block} editor={props.editor} />
      }
    )
  },
  inlineContentSpecs: {
    ...defaultInlineContentSpecs,
    mention: createReactInlineContentSpec(
      {
        type: "mention",
        content: "none",
        propSchema: {
          id: {
            default: ""
          },
          name: {
            default: ""
          }
        }
      },
      {
        render: props => {
          // mention 行内节点渲染（演示用）
          const { id } = props.inlineContent.props;
          return <span className="text-blue-500 bg-amber-200">@{id}</span>;
        }
      }
    )
  },
  styleSpecs: {
    ...defaultStyleSpecs
  }
});

// 文档加载阶段类型定义
type LoadingStage = "skeleton" | "snapshot" | "live";

// 骨架屏组件 - 模拟文档编辑器的加载状态
const DocumentSkeleton: React.FC = () => {
  return (
    <div className="absolute inset-0 pointer-events-none z-[5] animate-pulse bg-white">
      {/* 工具栏骨架 */}
      <div className="flex gap-2 p-2 border-b border-gray-200">
        {Array.from({ length: 5 }).map((_, i) => (
          <div key={i} className="h-8 w-8 bg-gray-200 rounded" />
        ))}
        <div className="ml-auto h-8 w-16 bg-gray-200 rounded" />
      </div>

      {/* 编辑区骨架 */}
      <div className="p-6 space-y-4">
        {/* 标题行 */}
        <div className="h-8 w-2/3 bg-gray-200 rounded" />

        {/* 段落行 */}
        {Array.from({ length: 8 }).map((_, i) => (
          <div key={i} className="space-y-2">
            <div className="h-4 w-full bg-gray-200 rounded" />
            <div className="h-4 w-5/6 bg-gray-200 rounded" />
            {i % 3 === 0 && <div className="h-4 w-4/5 bg-gray-200 rounded" />}
          </div>
        ))}

        {/* 块级元素骨架 */}
        <div className="h-32 w-full bg-gray-100 border border-gray-200 rounded-lg" />

        {/* 更多段落 */}
        {Array.from({ length: 4 }).map((_, i) => (
          <div key={i + 8} className="h-4 w-full bg-gray-200 rounded" />
        ))}
      </div>
    </div>
  );
};

// 生成随机颜色
function getRandomColor() {
  return `#${Math.floor(Math.random() * 0xffffff)
    .toString(16)
    .padStart(6, "0")}`;
}

// 生成随机用户名
function getRandomName() {
  return `user-${Math.random().toString(36).slice(2, 8)}`;
}

export function DocEditorDemo() {
  const params = useParams();
  const documentId: string = params.id || "";

  // 文档加载阶段状态管理
  const [loadingStage, setLoadingStage] = useState<LoadingStage>("skeleton");

  // 每个文档使用独立的 Y.Doc，避免多个文档之间状态串扰或残留
  const ydoc = useMemo(() => new Y.Doc(), [documentId]);

  // 离线编辑 + 本地存储 + 选主广播 + Worker 快照 的统一 Hook（保留原有逻辑与备注，迁移至 Hook 内部）
  const { isLeader, setProvider } = useOfflineDocSync({ documentId, ydoc });

  // 骨架屏控制回调函数
  // const markSnapshotReady = useCallback(() => {
  //   setLoadingStage(prev => (prev === "skeleton" ? "snapshot" : prev));
  // }, []);

  const markDocumentReady = useCallback(() => {
    setLoadingStage("live");
  }, []);

  // 根据 isLeader/documentId/ydoc 动态创建/销毁 provider，避免首次渲染拿不到 provider
  // 用途：
  // - 只有 Leader 创建并保持一个 WebSocket provider（CustomSocketProvider），避免同机重复连接/上报。
  // - Follower 返回 null（BlockNote 仍然可本地编辑，通过 BroadcastChannel 与 Leader 同步）。

  const provider = useMemo(() => {
    console.log(isLeader, "isLeader");
    if (!documentId || !isLeader) return null;
    return new CustomSocketProvider("http://localhost:7002", documentId, ydoc);
  }, [isLeader, documentId, ydoc]);

  // 清理：当依赖变化导致 provider 被替换或组件卸载时，销毁旧的 provider 断开连接。
  useEffect(() => {
    // 将 provider 注入到离线同步 Hook（用于 awareness 桥接与权限）
    setProvider(provider as any);
    return () => {
      try {
        (provider as any)?.destroy?.();
      } catch {}
    };
  }, [provider, setProvider]);

  // 由服务端权限驱动的可编辑状态（默认允许编辑；服务端可下发只读）
  const [editable, setEditable] = useState(true);

  const editor = useCreateBlockNote({
    schema,
    dictionary: zh,
    // === 协同编辑配置 ===
    collaboration: {
      // WebSocket 提供者：仅 Leader 连接；Follower 本地编辑并通过 BroadcastChannel 协同
      // 传入 undefined 表示不启用 provider（Follower 情况），但编辑器仍可本地编辑
      // @ts-ignore
      provider: provider || undefined,

      // 片段选择：作为 BlockNote 文档的协同根。需与服务端或历史保持一致。
      // 如果你的历史数据是保存在 "blocknote" 片段，请使用下行注释中的片段名。
      // fragment: ydoc.getXmlFragment("blocknote"),
      // 本项目示例按文档 ID 区分片段（示例二选一，确保前后端一致）
      fragment: ydoc.getXmlFragment(`document-${documentId}`),
      // 当前用户信息：用于显示光标和用户状态
      user: {
        name: getRandomName(), // 显示在光标旁边的用户名
        color: getRandomColor() // 光标和选择区域颜色
      },

      // 光标渲染函数：自定义其他用户光标的显示样式
      renderCursor: cursorRender
    },

    // 本地上传处理：返回本地对象 URL（演示用）。生产环境请替换为后端上传接口并返回可访问的 URL。
    uploadFile: async (file: File) => {
      const objectUrl = URL.createObjectURL(file);
      // 这里可以 设置写 文件切片上传！！
      return objectUrl;
    }

    // ⚠️ 注意：使用协同编辑时，不要设置 initialContent。内容应该来自协同 provider。
  });

  // 以上"离线编辑/本地存储/选主广播/Worker 快照/Awareness 桥接/周期快照"等复杂逻辑，均已抽离到 useOfflineDocSync 中，
  // 并完整保留了原有的中文备注与行为。

  // 文档初始加载完成检测 - 当编辑器首次渲染完成后隐藏骨架屏
  useEffect(() => {
    if (editor && documentId) {
      // 延迟一小段时间确保编辑器完全渲染完成
      const timer = setTimeout(() => {
        markDocumentReady();
      }, 500); // 500ms 后认为文档加载完成，可根据需要调整

      return () => clearTimeout(timer);
    }
  }, [editor, documentId, markDocumentReady]);

  // 监听服务端权限并切换编辑器可编辑状态（仅 Leader 持有 provider）
  // - 初始按 provider 当前状态设置（若服务端已下发）
  // - 订阅 permission 事件，动态切换可编辑
  useEffect(() => {
    const applyEditable = (canWrite: boolean) => {
      setEditable(!!canWrite);
    };

    if (provider) {
      // @ts-ignore
      applyEditable(!!provider.getCanWrite?.() || !!(provider as any).canWrite);
    }

    const off = (provider as any)?.onPermission?.(({ canWrite }: { canWrite: boolean }) => applyEditable(canWrite));
    return () => {
      if (typeof off === "function") off();
    };
  }, [editor, provider]);

  const getMentionUserItems = (e: typeof editor) => {
    const userItems: DefaultReactSuggestionItem[] = [
      {
        icon: <span>👤</span>,
        title: "用户123",
        onItemClick: () => {
          e.insertInlineContent([
            {
              type: "mention",
              props: { id: "User123", name: "用户123" }
            }
          ]);
        }
      },
      {
        icon: <span>👤</span>,
        title: "渡一用户123",
        onItemClick: () => {
          e.insertInlineContent([
            {
              type: "mention",
              props: { id: "User123", name: "用户123" }
            }
          ]);
        }
      }
    ];
    return userItems;
  };

  const insertBlockAI = (e: typeof editor) => {
    return {
      title: "AI助手",
      subtext: "为您提供智能建议",
      icon: <span>🤖</span>,
      onItemClick: () => {
        insertOrUpdateBlock(e, {
          type: "blockAI",
          props: {
            id: `ai-block-${Date.now()}`,
            title: "AI生成的标题",
            description: "AI生成的描述",
            content: "AI生成的内容"
          }
        });
      }
    };
  };

  const insertBlockSignature = (e: typeof editor) => {
    return {
      title: "签名",
      subtext: "为您提供签名块",
      icon: <span>✍️</span>,
      onItemClick: () => {
        insertOrUpdateBlock(e, {
          type: "blockSignature",
          props: {
            id: `signature-block-${Date.now()}`,
            name: "JACK"
          }
        });
      }
    };
  };

  // / 插入思维导图块
  const insertMindMap = (e: any) => ({
    title: "思维导图",
    subtext: "插入思维导图块",
    icon: <span>🧠</span>,
    onItemClick: () => {
      insertOrUpdateBlock(e, {
        type: "mindMap",
        props: {
          data: JSON.stringify({ nodeData: { id: "root", topic: "中心主题", children: [] } }),
          width: 900,
          height: 600
        }
      } as any);
    }
  });

  // 插入流程图
  const insertFlow = (editor: any) => ({
    title: "流程图",
    subtext: "插入流程图块",
    icon: <span>🔶</span>,
    onItemClick: () => insertOrUpdateBlock(editor, { type: "flowchart", props: { width: 900, height: 600 } as any })
  });

  // 插入白板（tldraw 2.x，方案一：JSON 快照）
  const insertWhiteboard = (e: any) => ({
    title: "白板",
    subtext: "插入 tldraw 白板块（JSON 快照）",
    icon: <span>🧩</span>,
    onItemClick: () => {
      insertOrUpdateBlock(e, {
        type: "whiteboard",
        props: {
          data: { version: 1, tldrawJson: null, preview: null, assets: [] },
          width: 900,
          height: 600
        }
      } as any);
    }
  });

  useEffect(() => {
    if (documentId) {
      // 这里可按需加载文档基础信息（标题、权限等）
    }
  }, [documentId]);

  const handleInvite = () => {
    console.log("邀请");
    fetch(`/api/documents/${documentId}/invite`, {
      method: "POST",
      credentials: "include",
      body: JSON.stringify({
        userId: 4,
        permission: "write"
        // write read
      }),
      headers: {
        "Content-Type": "application/json"
      }
    })
      .then(res => {
        if (!res.ok) {
          throw new Error(`HTTP ${res.status}: ${res.statusText}`);
        }
        return res.json();
      })
      .then(data => {
        console.log("验证响应:", data);
      });
  };

  const handleUndo = () => {
    try {
      editor.undo();
    } catch {}
  };

  const handleRedo = () => {
    try {
      editor.redo();
    } catch {}
  };

  return (
    <>
      <div className="relative min-h-screen">
        {/* 骨架屏 - 在文档完全加载前显示 */}
        {loadingStage !== "live" && <DocumentSkeleton />}

        {/* 工具栏 */}
        <div className="flex gap-2 p-2 border-b border-gray-200 relative z-10">
          <div
            className="w-[40px] h-[30px] text-[16px] bg-[#0ea43b] text-[#e2bc23] text-center leading-[30px] border-w-[1px] border-[#e2bc23] rounded-[10px] cursor-pointer"
            onClick={handleUndo}
          >
            撤销
          </div>
          <div
            className="w-[40px] h-[30px] text-[16px] bg-[#0ea43b] text-[#e2bc23] text-center leading-[30px] border-w-[1px] border-[#e2bc23] rounded-[10px] cursor-pointer"
            onClick={handleRedo}
          >
            重做
          </div>
          <div
            className="ml-auto w-[40px] h-[30px] text-[16px] bg-[#0ea43b] text-[#e2bc23] text-center leading-[30px] border-w-[1px] border-[#e2bc23] rounded-[10px] cursor-pointer"
            onClick={handleInvite}
          >
            邀请
          </div>
        </div>

        {/* 编辑器主体 */}
        <div className={`transition-opacity duration-300 ${loadingStage === "live" ? "opacity-100" : "opacity-0"}`}>
          <EditorErrorBoundary>
            <BlockNoteView editor={editor} slashMenu={false} editable={editable}>
              <SuggestionMenuController
                triggerCharacter="@"
                getItems={async query => {
                  return filterSuggestionItems(getMentionUserItems(editor), query);
                }}
              />
              <SuggestionMenuController
                triggerCharacter="/"
                getItems={async query => {
                  return filterSuggestionItems(
                    [
                      insertBlockSignature(editor),
                      insertBlockAI(editor),
                      insertMindMap(editor),
                      insertFlow(editor),
                      insertWhiteboard(editor),
                      ...getDefaultReactSlashMenuItems(editor)
                    ],
                    query
                  );
                }}
              />
            </BlockNoteView>
          </EditorErrorBoundary>
        </div>

        {/* 加载状态指示器 - 开发环境可见 */}
        {import.meta.env.DEV && (
          <div className="fixed bottom-4 left-4 bg-black text-white px-2 py-1 rounded text-xs z-50">
            Loading: {loadingStage}
          </div>
        )}
      </div>
    </>
  );
}
